package ws

// Worker represents a worker that executes tasks
type Worker struct {
	ID        int
	Task      chan *MsgTask
	Quit      chan bool
	IsWorking bool
}

func (w *Worker) start() {
	go func() {
		for {
			select {
			case task := <-w.Task:
				w.WorkerJob(task)
				w.IsWorking = false
			case <-w.Quit:
				return
			}
		}
	}()
}

func createNewWorker(id int) *Worker {
	worker := &Worker{
		ID:        id,
		Task:      make(chan *MsgTask),
		Quit:      make(chan bool),
		IsWorking: false,
	}
	worker.start()
	return worker
}

func (w *Worker) WorkerJob(task *MsgTask) {
	runTask(task)
}

// GoroutinePool manages a pool of workers
type GoroutinePool struct {
	Workers   []*Worker
	TaskQueue chan *MsgTask
	Quit      chan bool
}

var TaskPools *GoroutinePool

func (p *GoroutinePool) getWorker() *Worker {
	//找一个空闲的worker
	for _, wk := range p.Workers {
		if !wk.IsWorking {
			wk.IsWorking = true
			return wk
		}
	}
	//没找到,加个新的
	worker := createNewWorker(len(p.Workers))
	p.Workers = append(p.Workers, worker)
	return worker
}
func (p *GoroutinePool) dispatch() {
	for {
		select {
		case task := <-p.TaskQueue:
			worker := p.getWorker()
			worker.Task <- task
		case <-p.Quit:
			return
		}
	}
}

// AddMsgTask adds a task to the pool
func AddMsgTask(task *MsgTask) {
	TaskPools.TaskQueue <- task
}

// Stop stops the GoroutinePool and all its workers
func (p *GoroutinePool) Stop() {
	close(p.Quit)
	close(p.TaskQueue)
	for _, worker := range p.Workers {
		worker.Quit <- true
	}
}

// NewGoroutinePool creates a new GoroutinePool
func NewGoroutinePool(workerCount int) *GoroutinePool {
	pool := &GoroutinePool{
		TaskQueue: make(chan *MsgTask),
		Quit:      make(chan bool),
	}
	pool.Workers = make([]*Worker, workerCount)

	for i := 0; i < workerCount; i++ {
		pool.Workers[i] = createNewWorker(i)
	}

	go pool.dispatch()

	return pool
}

func init() {
	TaskPools = NewGoroutinePool(10) //上来先给10个进程
	/**
	for i := 0; i < 10; i++ {
		index := i
		pool.AddTask(func(id int) {
			fmt.Printf("Processing task %d by worker %d\n", index, id)
			time.Sleep(time.Millisecond * 3000) // Simulate work
		})
	}

	time.Sleep(time.Second) // Wait for tasks to be processed
	pool.Stop()
	fmt.Println("Pool stopped")
	/**/
}
